home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / source / dflt19 / normal.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-19  |  32.7 KB  |  1,108 lines

  1. /* ------------- normal.c ------------ */
  2.  
  3. #include "dflat.h"
  4.  
  5. #ifdef INCLUDE_MULTI_WINDOWS
  6. static void near PaintOverLappers(WINDOW wnd);
  7. static void near PaintUnderLappers(WINDOW wnd);
  8. #endif
  9.  
  10. static BOOL InsideWindow(WINDOW, int, int);
  11. static void TerminateMoveSize(void);
  12. static void SaveBorder(RECT);
  13. static void RestoreBorder(RECT);
  14. static void GetVideoBuffer(WINDOW);
  15. static void PutVideoBuffer(WINDOW);
  16. #ifdef INCLUDE_MINIMIZE
  17. static RECT PositionIcon(WINDOW);
  18. #endif
  19. static void near dragborder(WINDOW, int, int);
  20. static void near sizeborder(WINDOW, int, int);
  21. static int px = -1, py = -1;
  22. static int diff;
  23. static struct window dwnd = {DUMMY, NULL, NormalProc,
  24.                                 {-1,-1,-1,-1}};
  25. static int *Bsave;
  26. static int Bht, Bwd;
  27. BOOL WindowMoving;
  28. BOOL WindowSizing;
  29. /* -------- array of class definitions -------- */
  30. CLASSDEFS classdefs[] = {
  31.     #undef ClassDef
  32.     #define ClassDef(c,b,p,a) {b,p,a},
  33.     #include "classes.h"
  34. };
  35. WINDOW HiddenWindow;
  36.  
  37. /* --------- CREATE_WINDOW Message ---------- */
  38. static void CreateWindowMsg(WINDOW wnd)
  39. {
  40.     AppendWindow(wnd);
  41.     if (!SendMessage(NULL, MOUSE_INSTALLED, 0, 0))
  42.         ClearAttribute(wnd, VSCROLLBAR | HSCROLLBAR);
  43.     if (TestAttribute(wnd, SAVESELF) && isVisible(wnd))
  44.         GetVideoBuffer(wnd);
  45. }
  46.  
  47. /* --------- SHOW_WINDOW Message ---------- */
  48. static void ShowWindowMsg(WINDOW wnd, PARAM p1, PARAM p2)
  49. {
  50.     if (GetParent(wnd) == NULL || isVisible(GetParent(wnd)))    {
  51.         WINDOW cwnd;
  52.         if (TestAttribute(wnd, SAVESELF) &&
  53.                         wnd->videosave == NULL)
  54.             GetVideoBuffer(wnd);
  55.         SetVisible(wnd);
  56.         SendMessage(wnd, PAINT, 0, TRUE);
  57.         SendMessage(wnd, BORDER, 0, 0);
  58.         /* --- show the children of this window --- */
  59.         cwnd = FirstWindow(wnd);
  60.         while (cwnd != NULL)    {
  61.             if (cwnd->condition != ISCLOSING)
  62.                 SendMessage(cwnd, SHOW_WINDOW, p1, p2);
  63.             cwnd = NextWindow(cwnd);
  64.         }
  65.     }
  66. }
  67.  
  68. /* --------- HIDE_WINDOW Message ---------- */
  69. static void HideWindowMsg(WINDOW wnd)
  70. {
  71.     if (isVisible(wnd))    {
  72.         ClearVisible(wnd);
  73.         /* --- paint what this window covered --- */
  74.         if (TestAttribute(wnd, SAVESELF))
  75.             PutVideoBuffer(wnd);
  76. #ifdef INCLUDE_MULTI_WINDOWS
  77.         else
  78.             PaintOverLappers(wnd);
  79. #endif
  80.     }
  81. }
  82.  
  83. /* --------- KEYBOARD Message ---------- */
  84. static BOOL KeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2)
  85. {
  86.     if (WindowMoving || WindowSizing)    {
  87.         /* -- move or size a window with keyboard -- */
  88.         int x, y;
  89.         x=WindowMoving?GetLeft(&dwnd):GetRight(&dwnd);
  90.         y=WindowMoving?GetTop(&dwnd):GetBottom(&dwnd);
  91.         switch ((int)p1)    {
  92.             case ESC:
  93.                 TerminateMoveSize();
  94.                 return TRUE;
  95.             case UP:
  96.                 if (y)
  97.                     --y;
  98.                 break;
  99.             case DN:
  100.                 if (y < SCREENHEIGHT-1)
  101.                     y++;
  102.                 break;
  103.             case FWD:
  104.                 if (x < SCREENWIDTH-1)
  105.                     x++;
  106.                 break;
  107.             case BS:
  108.                 if (x)
  109.                     --x;
  110.                 break;
  111.             case '\r':
  112.                 SendMessage(wnd,BUTTON_RELEASED,x,y);
  113.             default:
  114.                 return TRUE;
  115.         }
  116.         /* -- use the mouse functions to move/size - */
  117.         SendMessage(wnd, MOUSE_CURSOR, x, y);
  118.         SendMessage(wnd, MOUSE_MOVED, x, y);
  119.         return TRUE;
  120.     }
  121.     switch ((int)p1)    {
  122.         case F1:
  123.             SendMessage(wnd, COMMAND, ID_HELP, 0);
  124.             return TRUE;
  125.         case ' ':
  126.             if ((int)p2 & ALTKEY)
  127.                 if (TestAttribute(wnd, HASTITLEBAR))
  128.                     if (TestAttribute(wnd, CONTROLBOX))
  129.                         BuildSystemMenu(wnd);
  130.             return TRUE;
  131.         case CTRL_F4:
  132.             if (TestAttribute(wnd, CONTROLBOX))    {
  133.                 SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  134.                 SkipApplicationControls();
  135.                 return TRUE;
  136.             }
  137.             break;
  138.         default:
  139.             break;
  140.     }
  141.     return FALSE;
  142. }
  143.  
  144. /* --------- COMMAND Message ---------- */
  145. static void CommandMsg(WINDOW wnd, PARAM p1)
  146. {
  147.     switch ((int)p1)    {
  148.         case ID_HELP:
  149.             DisplayHelp(wnd,ClassNames[GetClass(wnd)]);
  150.             break;
  151. #ifdef INCLUDE_RESTORE
  152.         case ID_SYSRESTORE:
  153.             SendMessage(wnd, RESTORE, 0, 0);
  154.             break;
  155. #endif
  156.         case ID_SYSMOVE:
  157.             SendMessage(wnd, CAPTURE_MOUSE, TRUE,
  158.                 (PARAM) &dwnd);
  159.             SendMessage(wnd, CAPTURE_KEYBOARD, TRUE,
  160.                 (PARAM) &dwnd);
  161.             SendMessage(wnd, MOUSE_CURSOR,
  162.                 GetLeft(wnd), GetTop(wnd));
  163.             WindowMoving = TRUE;
  164.             dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  165.             break;
  166.         case ID_SYSSIZE:
  167.             SendMessage(wnd, CAPTURE_MOUSE, TRUE,
  168.                 (PARAM) &dwnd);
  169.             SendMessage(wnd, CAPTURE_KEYBOARD, TRUE,
  170.                 (PARAM) &dwnd);
  171.             SendMessage(wnd, MOUSE_CURSOR,
  172.                 GetRight(wnd), GetBottom(wnd));
  173.             WindowSizing = TRUE;
  174.             dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  175.             break;
  176. #ifdef INCLUDE_MINIMIZE
  177.         case ID_SYSMINIMIZE:
  178.             SendMessage(wnd, MINIMIZE, 0, 0);
  179.             break;
  180. #endif
  181. #ifdef INCLUDE_MAXIMIZE
  182.         case ID_SYSMAXIMIZE:
  183.             SendMessage(wnd, MAXIMIZE, 0, 0);
  184.             break;
  185. #endif
  186.         case ID_SYSCLOSE:
  187.             SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  188.             SkipApplicationControls();
  189.             break;
  190.         default:
  191.             break;
  192.     }
  193. }
  194.  
  195. /* --------- SETFOCUS Message ---------- */
  196. static void SetFocusMsg(WINDOW wnd, PARAM p1)
  197. {
  198.     RECT rc = {0,0,0,0};
  199.     if (p1 && wnd != NULL && inFocus != wnd)    {
  200.         WINDOW this, thispar;
  201.         WINDOW that = NULL, thatpar = NULL;
  202.  
  203.         WINDOW cwnd = wnd, fwnd = GetParent(wnd);
  204.         /* ---- post focus in ancestors ---- */
  205.         while (fwnd != NULL)    {
  206.             fwnd->childfocus = cwnd;
  207.             cwnd = fwnd;
  208.             fwnd = GetParent(fwnd);
  209.         }
  210.         /* ---- de-post focus in self and children ---- */
  211.         fwnd = wnd;
  212.         while (fwnd != NULL)    {
  213.             cwnd = fwnd->childfocus;
  214.             fwnd->childfocus = NULL;
  215.             fwnd = cwnd;
  216.         }
  217.  
  218.         this = wnd;
  219.         that = thatpar = inFocus;
  220.  
  221.         /* ---- find common ancestor of prev focus and this window --- */
  222.         while (thatpar != NULL)    {
  223.             thispar = wnd;
  224.             while (thispar != NULL)    {
  225.                 if (this == CaptureMouse || this == CaptureKeyboard)    {
  226.                     /* ---- don't repaint if this window has capture ---- */
  227.                     that = thatpar = NULL;
  228.                     break;
  229.                 }
  230.                 if (thispar == thatpar)    {
  231.                     /* ---- don't repaint if SAVESELF window had focus ---- */
  232.                     if (this != that && TestAttribute(that, SAVESELF))
  233.                         that = thatpar = NULL;
  234.                     break;
  235.                 }
  236.                 this = thispar;
  237.                 thispar = GetParent(thispar);
  238.             }
  239.             if (thispar != NULL)
  240.                 break;
  241.             that = thatpar;
  242.             thatpar = GetParent(thatpar);
  243.         }
  244.         if (inFocus != NULL)
  245.             SendMessage(inFocus, SETFOCUS, FALSE, 0);
  246.         inFocus = wnd;
  247.         if (that != NULL && isVisible(wnd))    {
  248.             rc = subRectangle(WindowRect(that), WindowRect(this));
  249.             if (!ValidRect(rc))    {
  250.                 if (ApplicationWindow != NULL)    {
  251.                     WINDOW fwnd = FirstWindow(ApplicationWindow);
  252.                     while (fwnd != NULL)    {
  253.                         if (!isAncestor(wnd, fwnd))    {
  254.                             rc = subRectangle(WindowRect(wnd),WindowRect(fwnd));
  255.                             if (ValidRect(rc))
  256.                                 break;
  257.                         }
  258.                         fwnd = NextWindow(fwnd);
  259.                     }
  260.                 }
  261.             }
  262.         }
  263.         if (that != NULL && !ValidRect(rc) && isVisible(wnd))
  264.             this = NULL;
  265.         ReFocus(wnd);
  266.         if (this != NULL &&
  267.                 (!isVisible(this) || !TestAttribute(this, SAVESELF)))
  268.             SendMessage(this, SHOW_WINDOW, 0, 0);
  269.         else 
  270.             SendMessage(wnd, BORDER, 0, 0);
  271.     }
  272.     else if (!p1 && inFocus == wnd)    {
  273.         /* -------- clearing focus --------- */
  274.         inFocus = NULL;
  275.         SendMessage(wnd, BORDER, 0, 0);
  276.     }
  277. }
  278.  
  279. /* --------- DOUBLE_CLICK Message ---------- */
  280. static void DoubleClickMsg(WINDOW wnd, PARAM p1, PARAM p2)
  281. {
  282.     int mx = (int) p1 - GetLeft(wnd);
  283.     int my = (int) p2 - GetTop(wnd);
  284.     if (!WindowSizing && !WindowMoving)    {
  285.         if (HitControlBox(wnd, mx, my))    {
  286.             PostMessage(wnd, CLOSE_WINDOW, 0, 0);
  287.             SkipApplicationControls();
  288.         }
  289.     }
  290. }
  291.  
  292. /* --------- LEFT_BUTTON Message ---------- */
  293. static void LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
  294. {
  295.     int mx = (int) p1 - GetLeft(wnd);
  296.     int my = (int) p2 - GetTop(wnd);
  297.     if (WindowSizing || WindowMoving)
  298.         return;
  299.     if (HitControlBox(wnd, mx, my))    {
  300.         BuildSystemMenu(wnd);
  301.         return;
  302.     }
  303.     if (my == 0 && mx > -1 && mx < WindowWidth(wnd))  {
  304.         /* ---------- hit the top border -------- */
  305.         if (TestAttribute(wnd, MINMAXBOX) &&
  306.                 TestAttribute(wnd, HASTITLEBAR))  {
  307.             if (mx == WindowWidth(wnd)-2)    {
  308.                 if (wnd->condition != ISRESTORED)
  309.                     /* --- hit the restore box --- */
  310.                     SendMessage(wnd, RESTORE, 0, 0);
  311. #ifdef INCLUDE_MAXIMIZE
  312.                 else
  313.                     /* --- hit the maximize box --- */
  314.                     SendMessage(wnd, MAXIMIZE, 0, 0);
  315. #endif
  316.                 return;
  317.             }
  318. #ifdef INCLUDE_MINIMIZE
  319.             if (mx == WindowWidth(wnd)-3)    {
  320.                 /* --- hit the minimize box --- */
  321.                 if (wnd->condition != ISMINIMIZED)
  322.                     SendMessage(wnd, MINIMIZE, 0, 0);
  323.                 return;
  324.             }
  325. #endif
  326.         }
  327. #ifdef INCLUDE_MAXIMIZE
  328.         if (wnd->condition == ISMAXIMIZED)
  329.             return;
  330. #endif
  331.         if (TestAttribute(wnd, MOVEABLE))    {
  332.             WindowMoving = TRUE;
  333.             px = mx;
  334.             py = my;
  335.             diff = (int) mx;
  336.             SendMessage(wnd, CAPTURE_MOUSE, TRUE,
  337.                 (PARAM) &dwnd);
  338.             dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  339.         }
  340.         return;
  341.     }
  342.     if (mx == WindowWidth(wnd)-1 &&
  343.             my == WindowHeight(wnd)-1)    {
  344.         /* ------- hit the resize corner ------- */
  345. #ifdef INCLUDE_MINIMIZE
  346.         if (wnd->condition == ISMINIMIZED)
  347.             return;
  348. #endif
  349.         if (!TestAttribute(wnd, SIZEABLE))
  350.             return;
  351. #ifdef INCLUDE_MAXIMIZE
  352.         if (wnd->condition == ISMAXIMIZED)    {
  353.             if (GetParent(wnd) == NULL)
  354.                 return;
  355.             if (TestAttribute(GetParent(wnd),HASBORDER))
  356.                 return;
  357.             /* ----- resizing a maximized window over a
  358.                     borderless parent ----- */
  359.             wnd = GetParent(wnd);
  360.         }
  361. #endif
  362.         WindowSizing = TRUE;
  363.         SendMessage(wnd, CAPTURE_MOUSE,
  364.             TRUE, (PARAM) &dwnd);
  365.         dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  366.     }
  367. }
  368.  
  369. /* --------- MOUSE_MOVED Message ---------- */
  370. static BOOL MouseMovedMsg(WINDOW wnd, PARAM p1, PARAM p2)
  371. {
  372.     if (WindowMoving)    {
  373.         int leftmost = 0, topmost = 0,
  374.             bottommost = SCREENHEIGHT-2,
  375.             rightmost = SCREENWIDTH-2;
  376.         int x = (int) p1 - diff;
  377.         int y = (int) p2;
  378.         if (GetParent(wnd) != NULL &&
  379.                 !TestAttribute(wnd, NOCLIP))    {
  380.             WINDOW wnd1 = GetParent(wnd);
  381.             topmost    = GetClientTop(wnd1);
  382.             leftmost   = GetClientLeft(wnd1);
  383.             bottommost = GetClientBottom(wnd1);
  384.             rightmost  = GetClientRight(wnd1);
  385.         }
  386.         if (x < leftmost || x > rightmost ||
  387.                 y < topmost || y > bottommost)    {
  388.             x = max(x, leftmost);
  389.             x = min(x, rightmost);
  390.             y = max(y, topmost);
  391.             y = min(y, bottommost);
  392.             SendMessage(NULL,MOUSE_CURSOR,x+diff,y);
  393.         }
  394.         if (x != px || y != py)    {
  395.             px = x;
  396.             py = y;
  397.             dragborder(wnd, x, y);
  398.         }
  399.         return TRUE;
  400.     }
  401.     if (WindowSizing)    {
  402.         sizeborder(wnd, (int) p1, (int) p2);
  403.         return TRUE;
  404.     }
  405.     return FALSE;
  406. }
  407.  
  408. #ifdef INCLUDE_MAXIMIZE
  409. /* --------- MAXIMIZE Message ---------- */
  410. static void MaximizeMsg(WINDOW wnd)
  411. {
  412.     RECT rc = {0, 0, 0, 0};
  413.     RECT holdrc;
  414.     holdrc = wnd->RestoredRC;
  415.     rc.rt = SCREENWIDTH-1;
  416.     rc.bt = SCREENHEIGHT-1;
  417.     if (GetParent(wnd))
  418.         rc = ClientRect(GetParent(wnd));
  419.     wnd->oldcondition = wnd->condition;
  420.     wnd->condition = ISMAXIMIZED;
  421.     wnd->wasCleared = FALSE;
  422.     SendMessage(wnd, HIDE_WINDOW, 0, 0);
  423.     SendMessage(wnd, MOVE,
  424.         RectLeft(rc), RectTop(rc));
  425.     SendMessage(wnd, SIZE,
  426.         RectRight(rc), RectBottom(rc));
  427.     if (wnd->restored_attrib == 0)
  428.         wnd->restored_attrib = wnd->attrib;
  429.     ClearAttribute(wnd, SHADOW);
  430.     SendMessage(wnd, SHOW_WINDOW, 0, 0);
  431.     wnd->RestoredRC = holdrc;
  432. }
  433. #endif
  434.  
  435. #ifdef INCLUDE_MINIMIZE
  436. /* --------- MINIMIZE Message ---------- */
  437. static void MinimizeMsg(WINDOW wnd)
  438. {
  439.     RECT rc;
  440.     RECT holdrc;
  441.  
  442.     holdrc = wnd->RestoredRC;
  443.     rc = PositionIcon(wnd);
  444.     wnd->oldcondition = wnd->condition;
  445.     wnd->condition = ISMINIMIZED;
  446.     wnd->wasCleared = FALSE;
  447.     SendMessage(wnd, HIDE_WINDOW, 0, 0);
  448.     SendMessage(wnd, MOVE,
  449.         RectLeft(rc), RectTop(rc));
  450.     SendMessage(wnd, SIZE,
  451.         RectRight(rc), RectBottom(rc));
  452.     if (wnd == inFocus)
  453.         SetNextFocus();
  454.     if (wnd->restored_attrib == 0)
  455.         wnd->restored_attrib = wnd->attrib;
  456.     ClearAttribute(wnd,
  457.         SHADOW | SIZEABLE | HASMENUBAR |
  458.         VSCROLLBAR | HSCROLLBAR);
  459.     SendMessage(wnd, SHOW_WINDOW, 0, 0);
  460.     wnd->RestoredRC = holdrc;
  461. }
  462. #endif
  463.  
  464. #ifdef INCLUDE_RESTORE
  465. /* --------- RESTORE Message ---------- */
  466. static void RestoreMsg(WINDOW wnd)
  467. {
  468.     RECT holdrc;
  469.     holdrc = wnd->RestoredRC;
  470.     wnd->oldcondition = wnd->condition;
  471.     wnd->condition = ISRESTORED;
  472.     wnd->wasCleared = FALSE;
  473.     SendMessage(wnd, HIDE_WINDOW, 0, 0);
  474.     wnd->attrib = wnd->restored_attrib;
  475.     wnd->restored_attrib = 0;
  476.     SendMessage(wnd, MOVE, wnd->RestoredRC.lf,
  477.         wnd->RestoredRC.tp);
  478.     wnd->RestoredRC = holdrc;
  479.     SendMessage(wnd, SIZE, wnd->RestoredRC.rt,
  480.         wnd->RestoredRC.bt);
  481.     if (wnd != inFocus)
  482.         SendMessage(wnd, SETFOCUS, TRUE, 0);
  483.     else
  484.         SendMessage(wnd, SHOW_WINDOW, 0, 0);
  485. }
  486. #endif
  487.  
  488. /* --------- MOVE Message ---------- */
  489. static void MoveMsg(WINDOW wnd, PARAM p1, PARAM p2)
  490. {
  491.     WINDOW cwnd;
  492.     BOOL wasVisible = isVisible(wnd);
  493.     int xdif = (int) p1 - wnd->rc.lf;
  494.     int ydif = (int) p2 - wnd->rc.tp;
  495.  
  496.     if (xdif == 0 && ydif == 0)
  497.         return;
  498.     wnd->wasCleared = FALSE;
  499.     if (wasVisible)
  500.         SendMessage(wnd, HIDE_WINDOW, 0, 0);
  501.     wnd->rc.lf = (int) p1;
  502.     wnd->rc.tp = (int) p2;
  503.     wnd->rc.rt = GetLeft(wnd)+WindowWidth(wnd)-1;
  504.     wnd->rc.bt = GetTop(wnd)+WindowHeight(wnd)-1;
  505.     if (wnd->condition == ISRESTORED)
  506.         wnd->RestoredRC = wnd->rc;
  507.  
  508.     cwnd = FirstWindow(wnd);
  509.     while (cwnd != NULL)    {
  510.         SendMessage(cwnd, MOVE, cwnd->rc.lf+xdif, cwnd->rc.tp+ydif);
  511.         cwnd = NextWindow(cwnd);
  512.     }
  513.     if (wasVisible)
  514.         SendMessage(wnd, SHOW_WINDOW, 0, 0);
  515. }
  516.  
  517. /* --------- SIZE Message ---------- */
  518. static void SizeMsg(WINDOW wnd, PARAM p1, PARAM p2)
  519. {
  520.     BOOL wasVisible = isVisible(wnd);
  521.     WINDOW cwnd;
  522.     RECT rc;
  523.     int xdif = (int) p1 - wnd->rc.rt;
  524.     int ydif = (int) p2 - wnd->rc.bt;
  525.  
  526.     if (xdif == 0 && ydif == 0)
  527.         return;
  528.     wnd->wasCleared = FALSE;
  529.     if (wasVisible)
  530.         SendMessage(wnd, HIDE_WINDOW, 0, 0);
  531.     wnd->rc.rt = (int) p1;
  532.     wnd->rc.bt = (int) p2;
  533.     wnd->ht = GetBottom(wnd)-GetTop(wnd)+1;
  534.     wnd->wd = GetRight(wnd)-GetLeft(wnd)+1;
  535.  
  536.     if (wnd->condition == ISRESTORED)
  537.         wnd->RestoredRC = WindowRect(wnd);
  538.  
  539. #ifdef INCLUDE_MAXIMIZE
  540.     rc = ClientRect(wnd);
  541.  
  542.     cwnd = FirstWindow(wnd);
  543.     while (cwnd != NULL)    {
  544.         if (cwnd->condition == ISMAXIMIZED)
  545.             SendMessage(cwnd, SIZE, RectRight(rc), RectBottom(rc));
  546.         cwnd = NextWindow(cwnd);
  547.     }
  548.  
  549. #endif
  550.     if (wasVisible)
  551.         SendMessage(wnd, SHOW_WINDOW, 0, 0);
  552. }
  553.  
  554. /* --------- CLOSE_WINDOW Message ---------- */
  555. static void CloseWindowMsg(WINDOW wnd)
  556. {
  557.     WINDOW cwnd;
  558.     wnd->condition = ISCLOSING;
  559.     /* ----------- hide this window ------------ */
  560.     SendMessage(wnd, HIDE_WINDOW, 0, 0);
  561.  
  562.     /* --- close the children of this window --- */
  563.     cwnd = LastWindow(wnd);
  564.     while (cwnd != NULL)    {
  565.         if (inFocus == cwnd)
  566.             inFocus = wnd;
  567.         SendMessage(cwnd,CLOSE_WINDOW,0,0);
  568.         cwnd = LastWindow(wnd);
  569.     }
  570.  
  571.     /* ----- release captured resources ------ */
  572.     if (wnd->PrevClock != NULL)
  573.         SendMessage(wnd, RELEASE_CLOCK, 0, 0);
  574.     if (wnd->PrevMouse != NULL)
  575.         SendMessage(wnd, RELEASE_MOUSE, 0, 0);
  576.     if (wnd->PrevKeyboard != NULL)
  577.         SendMessage(wnd, RELEASE_KEYBOARD, 0, 0);
  578.  
  579.     /* --- change focus if this window had it -- */
  580.     if (wnd == inFocus)
  581.         SetPrevFocus();
  582.     /* -- free memory allocated to this window - */
  583.     if (wnd->title != NULL)
  584.         free(wnd->title);
  585.     if (wnd->videosave != NULL)
  586.         free(wnd->videosave);
  587.     /* -- remove window from parent's list of children -- */
  588.     RemoveWindow(wnd);
  589.     if (wnd == inFocus)
  590.         inFocus = NULL;
  591.     free(wnd);
  592. }
  593.  
  594. /* ---- Window-processing module for NORMAL window class ---- */
  595. int NormalProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  596. {
  597.     switch (msg)    {
  598.         case CREATE_WINDOW:
  599.             CreateWindowMsg(wnd);
  600.             break;
  601.         case SHOW_WINDOW:
  602.             ShowWindowMsg(wnd, p1, p2);
  603.             break;
  604.         case HIDE_WINDOW:
  605.             HideWindowMsg(wnd);
  606.             break;
  607.         case DISPLAY_HELP:
  608.             return DisplayHelp(wnd, (char *)p1);
  609.         case INSIDE_WINDOW:
  610.             return InsideWindow(wnd, (int) p1, (int) p2);
  611.         case KEYBOARD:
  612.             if (KeyboardMsg(wnd, p1, p2))
  613.                 return TRUE;
  614.             /* ------- fall through ------- */
  615.         case ADDSTATUS:
  616.         case SHIFT_CHANGED:
  617.             if (GetParent(wnd) != NULL)
  618.                 PostMessage(GetParent(wnd), msg, p1, p2);
  619.             break;
  620.         case PAINT:
  621.             if (isVisible(wnd))    {
  622. #ifdef INCLUDE_MULTI_WINDOWS
  623.                 if (wnd->wasCleared)
  624.                     PaintUnderLappers(wnd);
  625.                 else
  626. #endif
  627.                 {
  628.                     wnd->wasCleared = TRUE;
  629.                     ClearWindow(wnd, (RECT *)p1, ' ');
  630.                 }
  631.             }
  632.             break;
  633.         case BORDER:
  634.             if (isVisible(wnd))    {
  635.                 if (TestAttribute(wnd, HASBORDER))
  636.                     RepaintBorder(wnd, (RECT *)p1);
  637.                 else if (TestAttribute(wnd, HASTITLEBAR))
  638.                     DisplayTitle(wnd, (RECT *)p1);
  639.             }
  640.             break;
  641.         case COMMAND:
  642.             CommandMsg(wnd, p1);
  643.             break;
  644.         case SETFOCUS:
  645.             SetFocusMsg(wnd, p1);
  646.             break;
  647.         case DOUBLE_CLICK:
  648.             DoubleClickMsg(wnd, p1, p2);
  649.             break;
  650.         case LEFT_BUTTON:
  651.             LeftButtonMsg(wnd, p1, p2);
  652.             break;
  653.         case MOUSE_MOVED:
  654.             if (MouseMovedMsg(wnd, p1, p2))
  655.                 return TRUE;
  656.             break;
  657.         case BUTTON_RELEASED:
  658.             if (WindowMoving || WindowSizing)    {
  659.                 if (WindowMoving)
  660.                     PostMessage(wnd,MOVE,dwnd.rc.lf,dwnd.rc.tp);
  661.                 else
  662.                     PostMessage(wnd,SIZE,dwnd.rc.rt,dwnd.rc.bt);
  663.                 TerminateMoveSize();
  664.             }
  665.             break;
  666. #ifdef INCLUDE_MAXIMIZE
  667.         case MAXIMIZE:
  668.             if (wnd->condition != ISMAXIMIZED)
  669.                 MaximizeMsg(wnd);
  670.             break;
  671. #endif
  672. #ifdef INCLUDE_MINIMIZE
  673.         case MINIMIZE:
  674.             if (wnd->condition != ISMINIMIZED)
  675.                 MinimizeMsg(wnd);
  676.             break;
  677. #endif
  678. #ifdef INCLUDE_RESTORE
  679.         case RESTORE:
  680.             if (wnd->condition != ISRESTORED)    {
  681. #ifdef INCLUDE_MAXIMIZE
  682.                 if (wnd->oldcondition == ISMAXIMIZED)
  683.                     SendMessage(wnd, MAXIMIZE, 0, 0);
  684.                 else
  685. #endif
  686.                     RestoreMsg(wnd);
  687.             }
  688.             break;
  689. #endif
  690.         case MOVE:
  691.             MoveMsg(wnd, p1, p2);
  692.             break;
  693.         case SIZE:    {
  694.             SizeMsg(wnd, p1, p2);
  695.             break;
  696.         }
  697.         case CLOSE_WINDOW:
  698.             CloseWindowMsg(wnd);
  699.             break;
  700.         default:
  701.             break;
  702.     }
  703.     return TRUE;
  704. }
  705. #ifdef INCLUDE_MINIMIZE
  706. /* ---- compute lower right icon space in a rectangle ---- */
  707. static RECT LowerRight(RECT prc)
  708. {
  709.     RECT rc;
  710.     RectLeft(rc) = RectRight(prc) - ICONWIDTH;
  711.     RectTop(rc) = RectBottom(prc) - ICONHEIGHT;
  712.     RectRight(rc) = RectLeft(rc)+ICONWIDTH-1;
  713.     RectBottom(rc) = RectTop(rc)+ICONHEIGHT-1;
  714.     return rc;
  715. }
  716. /* ----- compute a position for a minimized window icon ---- */
  717. static RECT PositionIcon(WINDOW wnd)
  718. {
  719.     WINDOW pwnd = GetParent(wnd);
  720.     RECT rc;
  721.     RectLeft(rc) = SCREENWIDTH-ICONWIDTH;
  722.     RectTop(rc) = SCREENHEIGHT-ICONHEIGHT;
  723.     RectRight(rc) = SCREENWIDTH-1;
  724.     RectBottom(rc) = SCREENHEIGHT-1;
  725.     if (pwnd != NULL)    {
  726.         RECT prc = WindowRect(pwnd);
  727.         WINDOW cwnd = FirstWindow(pwnd);
  728.         rc = LowerRight(prc);
  729.         /* - search for icon available location - */
  730.         while (cwnd != NULL)    {
  731.             if (cwnd->condition == ISMINIMIZED)    {
  732.                 RECT rc1;
  733.                 rc1 = WindowRect(cwnd);
  734.                 if (RectLeft(rc1) == RectLeft(rc) &&
  735.                         RectTop(rc1) == RectTop(rc))    {
  736.                     RectLeft(rc) -= ICONWIDTH;
  737.                     RectRight(rc) -= ICONWIDTH;
  738.                     if (RectLeft(rc) < RectLeft(prc)+1)   {
  739.                         RectLeft(rc) =
  740.                             RectRight(prc)-ICONWIDTH;
  741.                         RectRight(rc) =
  742.                             RectLeft(rc)+ICONWIDTH-1;
  743.                         RectTop(rc) -= ICONHEIGHT;
  744.                         RectBottom(rc) -= ICONHEIGHT;
  745.                         if (RectTop(rc) < RectTop(prc)+1)
  746.                             return LowerRight(prc);
  747.                     }
  748.                     break;
  749.                 }
  750.             }
  751.             cwnd = NextWindow(cwnd);
  752.         }
  753.     }
  754.     return rc;
  755. }
  756. #endif
  757. /* ----- terminate the move or size operation ----- */
  758. static void TerminateMoveSize(void)
  759. {
  760.     px = py = -1;
  761.     diff = 0;
  762.     SendMessage(&dwnd, RELEASE_MOUSE, TRUE, 0);
  763.     SendMessage(&dwnd, RELEASE_KEYBOARD, TRUE, 0);
  764.     RestoreBorder(dwnd.rc);
  765.     WindowMoving = WindowSizing = FALSE;
  766. }
  767. /* ---- build a dummy window border for moving or sizing --- */
  768. static void near dragborder(WINDOW wnd, int x, int y)
  769. {
  770.     RestoreBorder(dwnd.rc);
  771.     /* ------- build the dummy window -------- */
  772.     dwnd.rc.lf = x;
  773.     dwnd.rc.tp = y;
  774.     dwnd.rc.rt = dwnd.rc.lf+WindowWidth(wnd)-1;
  775.     dwnd.rc.bt = dwnd.rc.tp+WindowHeight(wnd)-1;
  776.     dwnd.ht = WindowHeight(wnd);
  777.     dwnd.wd = WindowWidth(wnd);
  778.     dwnd.parent = GetParent(wnd);
  779.     dwnd.attrib = VISIBLE | HASBORDER | NOCLIP;
  780.     InitWindowColors(&dwnd);
  781.     SaveBorder(dwnd.rc);
  782.     RepaintBorder(&dwnd, NULL);
  783. }
  784. /* ---- write the dummy window border for sizing ---- */
  785. static void near sizeborder(WINDOW wnd, int rt, int bt)
  786. {
  787.     int leftmost = GetLeft(wnd)+10;
  788.     int topmost = GetTop(wnd)+3;
  789.     int bottommost = SCREENHEIGHT-1;
  790.     int rightmost  = SCREENWIDTH-1;
  791.     if (GetParent(wnd))    {
  792.         bottommost = min(bottommost,
  793.             GetClientBottom(GetParent(wnd)));
  794.         rightmost  = min(rightmost,
  795.             GetClientRight(GetParent(wnd)));
  796.     }
  797.     rt = min(rt, rightmost);
  798.     bt = min(bt, bottommost);
  799.     rt = max(rt, leftmost);
  800.     bt = max(bt, topmost);
  801.     SendMessage(NULL, MOUSE_CURSOR, rt, bt);
  802.  
  803.     if (rt != px || bt != py)
  804.         RestoreBorder(dwnd.rc);
  805.  
  806.     /* ------- change the dummy window -------- */
  807.     dwnd.ht = bt-dwnd.rc.tp+1;
  808.     dwnd.wd = rt-dwnd.rc.lf+1;
  809.     dwnd.rc.rt = rt;
  810.     dwnd.rc.bt = bt;
  811.     if (rt != px || bt != py)    {
  812.         px = rt;
  813.         py = bt;
  814.         SaveBorder(dwnd.rc);
  815.         RepaintBorder(&dwnd, NULL);
  816.     }
  817. }
  818. #ifdef INCLUDE_MULTI_WINDOWS
  819. /* ----- adjust a rectangle to include the shadow ----- */
  820. static RECT adjShadow(WINDOW wnd)
  821. {
  822.     RECT rc;
  823.     rc = wnd->rc;
  824.     if (TestAttribute(wnd, SHADOW))    {
  825.         if (RectRight(rc) < SCREENWIDTH-1)
  826.             RectRight(rc)++;           
  827.         if (RectBottom(rc) < SCREENHEIGHT-1)
  828.             RectBottom(rc)++;
  829.     }
  830.     return rc;
  831. }
  832. /* --- repaint a rectangular subsection of a window --- */
  833. static void near PaintOverLap(WINDOW wnd, RECT rc)
  834. {
  835.     if (isVisible(wnd))    {
  836.         int isBorder, isTitle, isData;
  837.         isBorder = isTitle = FALSE;
  838.         isData = TRUE;
  839.         if (TestAttribute(wnd, HASBORDER))    {
  840.             isBorder =  RectLeft(rc) == 0 &&
  841.                         RectTop(rc) < WindowHeight(wnd);
  842.             isBorder |= RectLeft(rc) < WindowWidth(wnd) &&
  843.                         RectRight(rc) >= WindowWidth(wnd)-1 &&
  844.                         RectTop(rc) < WindowHeight(wnd);
  845.             isBorder |= RectTop(rc) == 0 &&
  846.                         RectLeft(rc) < WindowWidth(wnd);
  847.             isBorder |= RectTop(rc) < WindowHeight(wnd) &&
  848.                         RectBottom(rc) >= WindowHeight(wnd)-1 &&
  849.                         RectLeft(rc) < WindowWidth(wnd);
  850.         }
  851.         else if (TestAttribute(wnd, HASTITLEBAR))
  852.             isTitle = RectTop(rc) == 0 &&
  853.                       RectRight(rc) > 0 &&
  854.                       RectLeft(rc)<WindowWidth(wnd)-BorderAdj(wnd);
  855.  
  856.         if (RectLeft(rc) >= WindowWidth(wnd)-BorderAdj(wnd))
  857.             isData = FALSE;
  858.         if (RectTop(rc) >= WindowHeight(wnd)-BottomBorderAdj(wnd))
  859.             isData = FALSE;
  860.         if (TestAttribute(wnd, HASBORDER))    {
  861.             if (RectRight(rc) == 0)
  862.                 isData = FALSE;
  863.             if (RectBottom(rc) == 0)
  864.                 isData = FALSE;
  865.         }
  866.         if (TestAttribute(wnd, SHADOW))
  867.             isBorder |= RectRight(rc) == WindowWidth(wnd) ||
  868.                         RectBottom(rc) == WindowHeight(wnd);
  869.         if (isData)
  870.             SendMessage(wnd, PAINT, (PARAM) &rc, TRUE);
  871.         if (isBorder)
  872.             SendMessage(wnd, BORDER, (PARAM) &rc, 0);
  873.         else if (isTitle)
  874.             DisplayTitle(wnd, &rc);
  875.     }
  876. }
  877. /* ------ paint the part of a window that is overlapped
  878.             by another window that is being hidden ------- */
  879. static void PaintOver(WINDOW wnd)
  880. {
  881.     RECT wrc, rc;
  882.     wrc = adjShadow(HiddenWindow);
  883.     rc = adjShadow(wnd);
  884.     rc = subRectangle(rc, wrc);
  885.     if (ValidRect(rc))
  886.         PaintOverLap(wnd, RelativeWindowRect(wnd, rc));
  887. }
  888. /* --- paint the overlapped parts of all children --- */
  889. static void PaintOverChildren(WINDOW pwnd)
  890. {
  891.     WINDOW cwnd = FirstWindow(pwnd);
  892.     while (cwnd != NULL)    {
  893.         if (cwnd != HiddenWindow)    {
  894.             PaintOver(cwnd);
  895.             PaintOverChildren(cwnd);
  896.         }
  897.         cwnd = NextWindow(cwnd);
  898.     }
  899. }
  900. /* -- recursive overlapping paint of parents -- */
  901. static void PaintOverParents(WINDOW wnd)
  902. {
  903.     WINDOW pwnd = GetParent(wnd);
  904.     if (pwnd != NULL)    {
  905.         PaintOverParents(pwnd);
  906.         PaintOver(pwnd);
  907.         PaintOverChildren(pwnd);
  908.     }
  909. }
  910. /* - paint the parts of all windows that a window is over - */
  911. static void near PaintOverLappers(WINDOW wnd)
  912. {
  913.     HiddenWindow = wnd;
  914.     PaintOverParents(wnd);
  915. }
  916. /* --- paint those parts of a window that are overlapped --- */
  917. static void near PaintUnderLappers(WINDOW wnd)
  918. {
  919.     WINDOW hwnd = NextWindow(wnd);
  920.     while (hwnd != NULL)    {
  921.         /* ------- test only at document window level ------ */
  922.         WINDOW pwnd = GetParent(hwnd);
  923. /*        if (pwnd == NULL || GetClass(pwnd) == APPLICATION)  */  {
  924.             /* ---- don't bother testing self ----- */
  925.             if (isVisible(hwnd) && hwnd != wnd)    {
  926.                 /* --- see if other window is descendent --- */
  927.                 while (pwnd != NULL)    {
  928.                     if (pwnd == wnd)
  929.                         break;
  930.                     pwnd = GetParent(pwnd);
  931.                 }
  932.                 /* ----- don't test descendent overlaps ----- */
  933.                 if (pwnd == NULL)    {
  934.                     /* -- see if other window is ancestor --- */
  935.                     pwnd = GetParent(wnd);
  936.                     while (pwnd != NULL)    {
  937.                         if (pwnd == hwnd)
  938.                             break;
  939.                         pwnd = GetParent(pwnd);
  940.                     }
  941.                     /* --- don't test ancestor overlaps --- */
  942.                     if (pwnd == NULL)    {
  943.                         HiddenWindow = GetAncestor(hwnd);
  944.                         ClearVisible(HiddenWindow);
  945.                         PaintOver(wnd);
  946.                         SetVisible(HiddenWindow);
  947.                     }
  948.                 }
  949.             }
  950.         }
  951.         hwnd = NextWindow(hwnd);
  952.     }
  953.     /* --------- repaint all children of this window
  954.         the same way ----------- */
  955.     hwnd = FirstWindow(wnd);
  956.     while (hwnd != NULL)    {
  957.         PaintUnderLappers(hwnd);
  958.         hwnd = NextWindow(hwnd);
  959.     }
  960. }
  961. #endif /* #ifdef INCLUDE_MULTI_WINDOWS */
  962.  
  963. /* --- save video area to be used by dummy window border --- */
  964. static void SaveBorder(RECT rc)
  965. {
  966.     RECT lrc;
  967.     int i;
  968.     int *cp;
  969.     Bht = RectBottom(rc) - RectTop(rc) + 1;
  970.     Bwd = RectRight(rc) - RectLeft(rc) + 1;
  971.     Bsave = DFrealloc(Bsave, (Bht + Bwd) * 4);
  972.  
  973.     lrc = rc;
  974.     RectBottom(lrc) = RectTop(lrc);
  975.     getvideo(lrc, Bsave);
  976.     RectTop(lrc) = RectBottom(lrc) = RectBottom(rc);
  977.     getvideo(lrc, Bsave + Bwd);
  978.     cp = Bsave + Bwd * 2;
  979.     for (i = 1; i < Bht-1; i++)    {
  980.         *cp++ = GetVideoChar(RectLeft(rc),RectTop(rc)+i);
  981.         *cp++ = GetVideoChar(RectRight(rc),RectTop(rc)+i);
  982.     }
  983. }
  984. /* ---- restore video area used by dummy window border ---- */
  985. static void RestoreBorder(RECT rc)
  986. {
  987.     if (Bsave != NULL)    {
  988.         RECT lrc;
  989.         int i;
  990.         int *cp;
  991.         lrc = rc;
  992.         RectBottom(lrc) = RectTop(lrc);
  993.         storevideo(lrc, Bsave);
  994.         RectTop(lrc) = RectBottom(lrc) = RectBottom(rc);
  995.         storevideo(lrc, Bsave + Bwd);
  996.         cp = Bsave + Bwd * 2;
  997.         for (i = 1; i < Bht-1; i++)    {
  998.             PutVideoChar(RectLeft(rc),RectTop(rc)+i, *cp++);
  999.             PutVideoChar(RectRight(rc),RectTop(rc)+i, *cp++);
  1000.         }
  1001.         free(Bsave);
  1002.         Bsave = NULL;
  1003.     }
  1004. }
  1005. /* ----- test if screen coordinates are in a window ---- */
  1006. static BOOL InsideWindow(WINDOW wnd, int x, int y)
  1007. {
  1008.     RECT rc;
  1009.     rc = WindowRect(wnd);
  1010.     if (!TestAttribute(wnd, NOCLIP))    {
  1011.         WINDOW pwnd = GetParent(wnd);
  1012.         while (pwnd != NULL)    {
  1013.             rc = subRectangle(rc, ClientRect(pwnd));
  1014.             pwnd = GetParent(pwnd);
  1015.         }
  1016.     }
  1017.     return InsideRect(x, y, rc);
  1018. }
  1019.  
  1020. BOOL isDerivedFrom(WINDOW wnd, CLASS class)
  1021. {
  1022.     CLASS tclass = GetClass(wnd);
  1023.     while (tclass != -1)    {
  1024.         if (tclass == class)
  1025.             return TRUE;
  1026.         tclass = (classdefs[tclass].base);
  1027.     }
  1028.     return FALSE;
  1029. }
  1030.  
  1031. /* -- find the oldest document window ancestor of a window -- */
  1032. WINDOW GetAncestor(WINDOW wnd)
  1033. {
  1034.     if (wnd != NULL)    {
  1035.         while (GetParent(wnd) != NULL)    {
  1036.             if (GetClass(GetParent(wnd)) == APPLICATION)
  1037.                 break;
  1038.             wnd = GetParent(wnd);
  1039.         }
  1040.     }
  1041.     return wnd;
  1042. }
  1043.  
  1044. BOOL isVisible(WINDOW wnd)
  1045. {
  1046.     while (wnd != NULL)    {
  1047.         if (isHidden(wnd))
  1048.             return FALSE;
  1049.         wnd = GetParent(wnd);
  1050.     }
  1051.     return TRUE;
  1052. }
  1053.  
  1054. /* -- adjust a window's rectangle to clip it to its parent - */
  1055. static RECT near ClipRect(WINDOW wnd)
  1056. {
  1057.     RECT rc;
  1058.     rc = WindowRect(wnd);
  1059.     if (TestAttribute(wnd, SHADOW))    {
  1060.         RectBottom(rc)++;
  1061.         RectRight(rc)++;
  1062.     }
  1063.     return ClipRectangle(wnd, rc);
  1064. }
  1065.  
  1066. /* -- get the video memory that is to be used by a window -- */
  1067. static void GetVideoBuffer(WINDOW wnd)
  1068. {
  1069.     RECT rc;
  1070.     int ht;
  1071.     int wd;
  1072.  
  1073.     rc = ClipRect(wnd);
  1074.     ht = RectBottom(rc) - RectTop(rc) + 1;
  1075.     wd = RectRight(rc) - RectLeft(rc) + 1;
  1076.     wnd->videosave = DFrealloc(wnd->videosave, (ht * wd * 2));
  1077.     get_videomode();
  1078.     getvideo(rc, wnd->videosave);
  1079. }
  1080.  
  1081. /* -- put the video memory that is used by a window -- */
  1082. static void PutVideoBuffer(WINDOW wnd)
  1083. {
  1084.     if (wnd->videosave != NULL)    {
  1085.         RECT rc;
  1086.         rc = ClipRect(wnd);
  1087.         get_videomode();
  1088.         storevideo(rc, wnd->videosave);
  1089.         free(wnd->videosave);
  1090.         wnd->videosave = NULL;
  1091.     }
  1092. }
  1093.  
  1094. /* ------- return TRUE if awnd is an ancestor of wnd ------- */
  1095. BOOL isAncestor(WINDOW wnd, WINDOW awnd)
  1096. {
  1097.     while (wnd != NULL)    {
  1098.         if (wnd == awnd)
  1099.             return TRUE;
  1100.         wnd = GetParent(wnd);
  1101.     }
  1102.     return FALSE;
  1103. }
  1104.  
  1105.  
  1106.  
  1107. 
  1108.